#include "Spawner.h"

#include "Door.h"
#include "GameObject.h"
#include "Gate.h"
#include "BagOfGold.h"
#include "Key.h"
#include "Monster.h"
#include "Movable.h"
#include "GameObjectManager.h"
#include "Player.h"
#include "Projectile.h"
#include "Room.h"
#include "Tile.h"
#include "Wall.h"

#include <assert.h>
#include <iostream>

Spawner* Spawner::spawner = 0;


Spawner* Spawner::getInstance()
{
	if (!spawner)
	{
		spawner = new Spawner();
	}
	return spawner;
}


void Spawner::destroyInstance()
{
	delete spawner;
	spawner = 0;
}


GameObject* Spawner::spawn(char id, int x, int y, int hDirection, int vDirection, Player* owner)
{
	assert(map);

	GameObject* object = 0;

	// Create object based on id.
	switch(id)
	{
	case ID_BagOfGold:	object = new BagOfGold(x, y); break;
	case ID_Door:		object = new Door(x, y); break;
	case ID_Gate:		object = new Gate(x, y); break;
	case ID_Key:		object = new Key(x, y); break;
	case ID_GateKey:	object = new Key(x, y, Player::InventoryItem_GateKey); break;
	case ID_Monster:	object = new Monster(x, y, *map); break;
	case ID_PlayerOne:	object = new Player(1, x, y); break;
	case ID_PlayerTwo:	object = new Player(2, x, y); break;
	case ID_Projectile:	object = new Projectile(x, y, hDirection, vDirection, owner); break;
	case ID_Room:		object = new Room(x, y); break;
	case ID_Wall:		object = new Wall(x, y); break;
	case ID_Empty:		return 0;
	default: std::cout << "Unsupported character: '" << id << "' found in Spawner::spawn. " << std::endl; break;
	}

	// Don't create if there is no room on the map.
	if (!(*map)[y][x]->isPassable(object))
	{
		delete object;
		return 0;
	}
	
	if (object)
	{
		(*map)[y][x]->add(object);

		// Register at the movable manager if this is a movable.
		Movable* spawnedMovable = dynamic_cast<Movable*>(object);
		if (spawnedMovable)
		{
			GameObjectManager::getInstance()->registerMovable(spawnedMovable);
		}
	}

	return object;
}


void Spawner::setMap(Map* map)
{
	this->map = map;
}


Spawner::Spawner() :
	map(0)
{
}